Luciole

Communication instantanée
pour élèves pilotes
sourds & malentendants

Julien Le Guen

2025-01-27

Qui dans l’assemblée…

  • Fait du Rust

  • Fait de l’embarqué

  • Fait du parapente

  • Enseigne

  • N’a pas encore levé la main :)

?

Enseignement du parapente

Progression en école

Petit groupe, encadrés par deux moniteurs

Pratique

10 % de la formation


90 % restant ?

Aller vers l’autonomie

  • Initiation

  • Progression

  • Perfectionnement

  • Cross

  • SIV

  • Au début, découverte, petits vols, gestion du stress

  • Puis apprendre à rester en l’air

  • Puis apprendre à se déplacer, voyager !

Progression autonome

  • Collecte d’informations
  • Prises de décision
  • Anticipation
  • PLAISIR

Eleves Sourds

Communication radio impossible.

Existant

  • Radios vibrantes (2 signaux possibles)

  • Lunettes à LED gauche/droite

  • WhatsApp

Besoins

  • Communication unidirectionnelle
  • Instantanée
  • Indication précise si besoin (commande gauche, un peu plus…)
  • Indication de haut niveau -> autonomisation
  • Non intrusif (champ de vision)
  • Intuitif pour l’élève et le moniteur
  • Configurable en fonction du stage et de l’exercice

Système Luciole

Principe

Matériel

  • 2x systèmes radios
  • Manette de jeu
  • Lunettes ActiveLook
  • Modules vibrants (bracelets)

Fonctionalités

  • Temps-réel : Vibrations

  • Consignes haut-niveau : Lunettes

  • Lien radio numérique

    • Adressage
    • Ack, renvoi de message
    • Heartbeat

Rust Embarqué

Stack Technique

  • embedded-hal v1.0 🥳

  • Radios : cible ESP32 (xtensa)

    • SDK Espressif, surcouche Rust à esp-idf (FreeRTOS)
  • Vibreurs : cible nRF52840 (arm cortex-M)

    • embassy EMBedded ASYnc :)
    • Blob BLE Nordic

Architecture Système

Côté Moniteur – Émetteur

Côté Moniteur – Détails

Architecture Système

Côté Élève – Récepteur

Côté Élève – Détails

Côté Élève – Trop de détails

Développement

  • Tests sur PC de dev et CI/CD

  • Réutiliser ce qui est possible

    • Extraire des crates sx127x_driver, infos_metier, …
  • Limiter le code hardware-dependant

  • Traits :)

Rust pour l´Embarqué

  • Traits (interfaces)

  • Ecosystème mature

    • embedded-hal
    • Cargo, esp-rs, etc.
  • “Si ça compile, ça marche”

  • Force les bonnes pratiques

  • Stage de 5 mois -> Jordan (néophyte) produit un système qui fonctionne !

Lunettes ActiveLook

Communication

SDK Android & iOS

BLE API

  • Protocole bit-oriented
  • Compliqué

Rust

Crate activelook-rs

  • Primitives haut-niveau
  • Commandes, packets, protocole, …
  • Serialization avec deku
pub enum Command {
    PowerDisplay { en: u8 },
    Clear,
    Rect { from: Point, to: Point },
    // And countless other commands
}

Problèmes de l’embarqué

  • Une seule paire de lunettes

  • Cycle relativement long (flasher la radio, reboot, connexion au lunettes, etc.)

  • Très manuel

  • Comment tester la crate activelook-rs ?

  • Comment mettre au point les écrans pour l’application finale ?

Tests


    #[test]
    fn test_packet_serialization() {
        let expected = [0xFF, 0x00, 0x00, 0x06, 0x01, 0xAA];
        let expected_cmd = Command::PowerDisplay { en: 1 };
        let cmd = Command::PowerDisplay { en: 1 };
        let packet = Packet::new(&cmd);
        // Serialization
        let bytes = packet.to_bytes();
        assert_eq!(expected, bytes[..]);

        // Deserialization
        let newpkt = CommandPacket::from_bytes(&bytes).expect("Unable to deserialize");
        assert_eq!(expected_cmd, newpkt.data);
    }

Émulateur ActiveLook

  • Serveur ØMQ
  • Graphisme nannou
  • Utilise activelook-rs et le protocole BLE comme le vrai HW
let cmds = [
    Command::PowerDisplay { en: 1 },
    Command::Clear,
    // Outside
    Command::Rect {
        from: Point { x: 0, y: 0 },
        to: Point { x: 303, y: 255 },
    },
    // ...
];
for cmd in cmds {
    client.send(&cmd);
}

Credits

jlg@jleguen.info

Crates

Graphics